Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1168)

Side by Side Diff: src/sksl/SkSLIRGenerator.cpp

Issue 2427693002: more skslc hardening (Closed)
Patch Set: added another test Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/sksl/ir/SkSLTypeReference.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2016 Google Inc. 2 * Copyright 2016 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkSLIRGenerator.h" 8 #include "SkSLIRGenerator.h"
9 9
10 #include "limits.h" 10 #include "limits.h"
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
197 auto var = std::unique_ptr<Variable>(new Variable(decl.fPosition, modifi ers, varDecl.fName, 197 auto var = std::unique_ptr<Variable>(new Variable(decl.fPosition, modifi ers, varDecl.fName,
198 *type, storage)); 198 *type, storage));
199 std::unique_ptr<Expression> value; 199 std::unique_ptr<Expression> value;
200 if (varDecl.fValue) { 200 if (varDecl.fValue) {
201 value = this->convertExpression(*varDecl.fValue); 201 value = this->convertExpression(*varDecl.fValue);
202 if (!value) { 202 if (!value) {
203 return nullptr; 203 return nullptr;
204 } 204 }
205 value = this->coerce(std::move(value), *type); 205 value = this->coerce(std::move(value), *type);
206 } 206 }
207 if ("sk_FragColor" == varDecl.fName && (*fSymbolTable)[varDecl.fName]) { 207 if (storage == Variable::kGlobal_Storage && "sk_FragColor" == varDecl.fN ame &&
208 (*fSymbolTable)[varDecl.fName]) {
208 // already defined, ignore 209 // already defined, ignore
209 } else if ((*fSymbolTable)[varDecl.fName] && 210 } else if (storage == Variable::kGlobal_Storage && (*fSymbolTable)[varDe cl.fName] &&
210 (*fSymbolTable)[varDecl.fName]->fKind == Symbol::kVariable_Ki nd && 211 (*fSymbolTable)[varDecl.fName]->fKind == Symbol::kVariable_Ki nd &&
211 ((Variable*) (*fSymbolTable)[varDecl.fName])->fModifiers.fLay out.fBuiltin >= 0) { 212 ((Variable*) (*fSymbolTable)[varDecl.fName])->fModifiers.fLay out.fBuiltin >= 0) {
212 // already defined, just update the modifiers 213 // already defined, just update the modifiers
213 Variable* old = (Variable*) (*fSymbolTable)[varDecl.fName]; 214 Variable* old = (Variable*) (*fSymbolTable)[varDecl.fName];
214 old->fModifiers = var->fModifiers; 215 old->fModifiers = var->fModifiers;
215 } else { 216 } else {
216 variables.emplace_back(var.get(), std::move(sizes), std::move(value) ); 217 variables.emplace_back(var.get(), std::move(sizes), std::move(value) );
217 fSymbolTable->add(varDecl.fName, std::move(var)); 218 fSymbolTable->add(varDecl.fName, std::move(var));
218 } 219 }
219 } 220 }
220 return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fPosition, 221 return std::unique_ptr<VarDeclarations>(new VarDeclarations(decl.fPosition,
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 args.push_back(std::move(expr)); 671 args.push_back(std::move(expr));
671 return std::unique_ptr<Expression>(new Constructor(Position(), type, std::mo ve(args))); 672 return std::unique_ptr<Expression>(new Constructor(Position(), type, std::mo ve(args)));
672 } 673 }
673 674
674 static bool is_matrix_multiply(const Type& left, const Type& right) { 675 static bool is_matrix_multiply(const Type& left, const Type& right) {
675 if (left.kind() == Type::kMatrix_Kind) { 676 if (left.kind() == Type::kMatrix_Kind) {
676 return right.kind() == Type::kMatrix_Kind || right.kind() == Type::kVect or_Kind; 677 return right.kind() == Type::kMatrix_Kind || right.kind() == Type::kVect or_Kind;
677 } 678 }
678 return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Ki nd; 679 return left.kind() == Type::kVector_Kind && right.kind() == Type::kMatrix_Ki nd;
679 } 680 }
681
682 static bool is_assignment(Token::Kind op) {
683 switch (op) {
684 case Token::EQ: // fall through
685 case Token::PLUSEQ: // fall through
686 case Token::MINUSEQ: // fall through
687 case Token::STAREQ: // fall through
688 case Token::SLASHEQ: // fall through
689 case Token::PERCENTEQ: // fall through
690 case Token::SHLEQ: // fall through
691 case Token::SHREQ: // fall through
692 case Token::BITWISEOREQ: // fall through
693 case Token::BITWISEXOREQ: // fall through
694 case Token::BITWISEANDEQ: // fall through
695 case Token::LOGICALOREQ: // fall through
696 case Token::LOGICALXOREQ: // fall through
697 case Token::LOGICALANDEQ:
698 return true;
699 default:
700 return false;
701 }
702 }
703
680 /** 704 /**
681 * Determines the operand and result types of a binary expression. Returns true if the expression is 705 * Determines the operand and result types of a binary expression. Returns true if the expression is
682 * legal, false otherwise. If false, the values of the out parameters are undefi ned. 706 * legal, false otherwise. If false, the values of the out parameters are undefi ned.
683 */ 707 */
684 static bool determine_binary_type(const Context& context, 708 static bool determine_binary_type(const Context& context,
685 Token::Kind op, 709 Token::Kind op,
686 const Type& left, 710 const Type& left,
687 const Type& right, 711 const Type& right,
688 const Type** outLeftType, 712 const Type** outLeftType,
689 const Type** outRightType, 713 const Type** outRightType,
690 const Type** outResultType, 714 const Type** outResultType,
691 bool tryFlipped) { 715 bool tryFlipped) {
692 bool isLogical; 716 bool isLogical;
717 bool validMatrixOrVectorOp;
693 switch (op) { 718 switch (op) {
719 case Token::EQ:
720 *outLeftType = &left;
721 *outRightType = &left;
722 *outResultType = &left;
723 return right.canCoerceTo(left);
694 case Token::EQEQ: // fall through 724 case Token::EQEQ: // fall through
695 case Token::NEQ: // fall through 725 case Token::NEQ:
726 isLogical = true;
727 validMatrixOrVectorOp = true;
728 break;
696 case Token::LT: // fall through 729 case Token::LT: // fall through
697 case Token::GT: // fall through 730 case Token::GT: // fall through
698 case Token::LTEQ: // fall through 731 case Token::LTEQ: // fall through
699 case Token::GTEQ: 732 case Token::GTEQ:
700 isLogical = true; 733 isLogical = true;
734 validMatrixOrVectorOp = false;
701 break; 735 break;
702 case Token::LOGICALOR: // fall through 736 case Token::LOGICALOR: // fall through
703 case Token::LOGICALAND: // fall through 737 case Token::LOGICALAND: // fall through
704 case Token::LOGICALXOR: // fall through 738 case Token::LOGICALXOR: // fall through
705 case Token::LOGICALOREQ: // fall through 739 case Token::LOGICALOREQ: // fall through
706 case Token::LOGICALANDEQ: // fall through 740 case Token::LOGICALANDEQ: // fall through
707 case Token::LOGICALXOREQ: 741 case Token::LOGICALXOREQ:
708 *outLeftType = context.fBool_Type.get(); 742 *outLeftType = context.fBool_Type.get();
709 *outRightType = context.fBool_Type.get(); 743 *outRightType = context.fBool_Type.get();
710 *outResultType = context.fBool_Type.get(); 744 *outResultType = context.fBool_Type.get();
(...skipping 30 matching lines...) Expand all
741 } else { 775 } else {
742 // result was a column vector, transpose it back to a ro w 776 // result was a column vector, transpose it back to a ro w
743 *outResultType = &(*outResultType)->toCompound(context, leftRows, 777 *outResultType = &(*outResultType)->toCompound(context, leftRows,
744 rightColu mns); 778 rightColu mns);
745 } 779 }
746 return leftColumns == rightRows; 780 return leftColumns == rightRows;
747 } else { 781 } else {
748 return false; 782 return false;
749 } 783 }
750 } 784 }
751 // fall through 785 isLogical = false;
786 validMatrixOrVectorOp = true;
787 break;
788 case Token::PLUS: // fall through
789 case Token::PLUSEQ: // fall through
790 case Token::MINUS: // fall through
791 case Token::MINUSEQ: // fall through
792 case Token::SLASH: // fall through
793 case Token::SLASHEQ:
794 isLogical = false;
795 validMatrixOrVectorOp = true;
796 break;
752 default: 797 default:
753 isLogical = false; 798 isLogical = false;
799 validMatrixOrVectorOp = false;
754 } 800 }
755 // FIXME: need to disallow illegal operations like vec3 > vec3. Also do not currently have 801 bool isVectorOrMatrix = left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind;
756 // full support for numbers other than float. 802 // FIXME: incorrect for shift
757 if (left == right) { 803 if (right.canCoerceTo(left) && (left.kind() == Type::kScalar_Kind ||
804 (isVectorOrMatrix && validMatrixOrVectorOp))) {
758 *outLeftType = &left; 805 *outLeftType = &left;
759 *outRightType = &left; 806 *outRightType = &left;
760 if (isLogical) { 807 if (isLogical) {
761 *outResultType = context.fBool_Type.get(); 808 *outResultType = context.fBool_Type.get();
762 } else { 809 } else {
763 *outResultType = &left; 810 *outResultType = &left;
764 } 811 }
765 return true; 812 return true;
766 } 813 }
767 // FIXME: incorrect for shift operations
768 if (left.canCoerceTo(right)) {
769 *outLeftType = &right;
770 *outRightType = &right;
771 if (isLogical) {
772 *outResultType = context.fBool_Type.get();
773 } else {
774 *outResultType = &right;
775 }
776 return true;
777 }
778 if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) && 814 if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) &&
779 (right.kind() == Type::kScalar_Kind)) { 815 (right.kind() == Type::kScalar_Kind)) {
780 if (determine_binary_type(context, op, left.componentType(), right, outL eftType, 816 if (determine_binary_type(context, op, left.componentType(), right, outL eftType,
781 outRightType, outResultType, false)) { 817 outRightType, outResultType, false)) {
782 *outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows()); 818 *outLeftType = &(*outLeftType)->toCompound(context, left.columns(), left.rows());
783 if (!isLogical) { 819 if (!isLogical) {
784 *outResultType = &(*outResultType)->toCompound(context, left.col umns(), 820 *outResultType = &(*outResultType)->toCompound(context, left.col umns(),
785 left.rows()); 821 left.rows());
786 } 822 }
787 return true; 823 return true;
(...skipping 14 matching lines...) Expand all
802 return nullptr; 838 return nullptr;
803 } 839 }
804 std::unique_ptr<Expression> right = this->convertExpression(*expression.fRig ht); 840 std::unique_ptr<Expression> right = this->convertExpression(*expression.fRig ht);
805 if (!right) { 841 if (!right) {
806 return nullptr; 842 return nullptr;
807 } 843 }
808 const Type* leftType; 844 const Type* leftType;
809 const Type* rightType; 845 const Type* rightType;
810 const Type* resultType; 846 const Type* resultType;
811 if (!determine_binary_type(fContext, expression.fOperator, left->fType, righ t->fType, &leftType, 847 if (!determine_binary_type(fContext, expression.fOperator, left->fType, righ t->fType, &leftType,
812 &rightType, &resultType, true)) { 848 &rightType, &resultType, !is_assignment(expressio n.fOperator))) {
813 fErrors.error(expression.fPosition, "type mismatch: '" + 849 fErrors.error(expression.fPosition, "type mismatch: '" +
814 Token::OperatorName(expression.fOper ator) + 850 Token::OperatorName(expression.fOper ator) +
815 "' cannot operate on '" + left->fTyp e.fName + 851 "' cannot operate on '" + left->fTyp e.fName +
816 "', '" + right->fType.fName + "'"); 852 "', '" + right->fType.fName + "'");
817 return nullptr; 853 return nullptr;
818 } 854 }
819 switch (expression.fOperator) { 855 if (is_assignment(expression.fOperator)) {
820 case Token::EQ: // fall through 856 this->markWrittenTo(*left);
821 case Token::PLUSEQ: // fall through 857 }
822 case Token::MINUSEQ: // fall through 858 left = this->coerce(std::move(left), *leftType);
823 case Token::STAREQ: // fall through 859 right = this->coerce(std::move(right), *rightType);
824 case Token::SLASHEQ: // fall through 860 if (!left || !right) {
825 case Token::PERCENTEQ: // fall through 861 return nullptr;
826 case Token::SHLEQ: // fall through
827 case Token::SHREQ: // fall through
828 case Token::BITWISEOREQ: // fall through
829 case Token::BITWISEXOREQ: // fall through
830 case Token::BITWISEANDEQ: // fall through
831 case Token::LOGICALOREQ: // fall through
832 case Token::LOGICALXOREQ: // fall through
833 case Token::LOGICALANDEQ:
834 this->markWrittenTo(*left);
835 default:
836 break;
837 } 862 }
838 return std::unique_ptr<Expression>(new BinaryExpression(expression.fPosition , 863 return std::unique_ptr<Expression>(new BinaryExpression(expression.fPosition ,
839 this->coerce(std::mo ve(left), 864 std::move(left),
840 *leftTy pe),
841 expression.fOperator , 865 expression.fOperator ,
842 this->coerce(std::mo ve(right), 866 std::move(right),
843 *rightT ype),
844 *resultType)); 867 *resultType));
845 } 868 }
846 869
847 std::unique_ptr<Expression> IRGenerator::convertTernaryExpression( 870 std::unique_ptr<Expression> IRGenerator::convertTernaryExpression(
848 const ASTTernaryExpre ssion& expression) { 871 const ASTTernaryExpre ssion& expression) {
849 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*exp ression.fTest), 872 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*exp ression.fTest),
850 *fContext.fBool_Type); 873 *fContext.fBool_Type);
851 if (!test) { 874 if (!test) {
852 return nullptr; 875 return nullptr;
853 } 876 }
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
887 " argument"; 910 " argument";
888 if (function.fParameters.size() != 1) { 911 if (function.fParameters.size() != 1) {
889 msg += "s"; 912 msg += "s";
890 } 913 }
891 msg += ", but found " + to_string((uint64_t) arguments.size()); 914 msg += ", but found " + to_string((uint64_t) arguments.size());
892 fErrors.error(position, msg); 915 fErrors.error(position, msg);
893 return nullptr; 916 return nullptr;
894 } 917 }
895 for (size_t i = 0; i < arguments.size(); i++) { 918 for (size_t i = 0; i < arguments.size(); i++) {
896 arguments[i] = this->coerce(std::move(arguments[i]), function.fParameter s[i]->fType); 919 arguments[i] = this->coerce(std::move(arguments[i]), function.fParameter s[i]->fType);
920 if (!arguments[i]) {
921 return nullptr;
922 }
897 if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifi ers::kOut_Flag)) { 923 if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifi ers::kOut_Flag)) {
898 this->markWrittenTo(*arguments[i]); 924 this->markWrittenTo(*arguments[i]);
899 } 925 }
900 } 926 }
901 return std::unique_ptr<FunctionCall>(new FunctionCall(position, function, 927 return std::unique_ptr<FunctionCall>(new FunctionCall(position, function,
902 std::move(arguments))) ; 928 std::move(arguments))) ;
903 } 929 }
904 930
905 /** 931 /**
906 * Determines the cost of coercing the arguments of a function to the required t ypes. Returns true 932 * Determines the cost of coercing the arguments of a function to the required t ypes. Returns true
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
984 } 1010 }
985 if (args.size() == 1 && args[0]->fType == type) { 1011 if (args.size() == 1 && args[0]->fType == type) {
986 // argument is already the right type, just return it 1012 // argument is already the right type, just return it
987 return std::move(args[0]); 1013 return std::move(args[0]);
988 } 1014 }
989 if (type.isNumber()) { 1015 if (type.isNumber()) {
990 if (args.size() != 1) { 1016 if (args.size() != 1) {
991 fErrors.error(position, "invalid arguments to '" + type.description( ) + 1017 fErrors.error(position, "invalid arguments to '" + type.description( ) +
992 "' constructor, (expected exactly 1 argument , but found " + 1018 "' constructor, (expected exactly 1 argument , but found " +
993 to_string((uint64_t) args.size()) + ")"); 1019 to_string((uint64_t) args.size()) + ")");
1020 return nullptr;
994 } 1021 }
995 if (args[0]->fType == *fContext.fBool_Type) { 1022 if (args[0]->fType == *fContext.fBool_Type) {
996 std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, position, 0)); 1023 std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, position, 0));
997 std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, position, 1 )); 1024 std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, position, 1 ));
998 return std::unique_ptr<Expression>( 1025 return std::unique_ptr<Expression>(
999 new TernaryExpression(position, std::mo ve(args[0]), 1026 new TernaryExpression(position, std::mo ve(args[0]),
1000 this->coerce(std: :move(one), type), 1027 this->coerce(std: :move(one), type),
1001 this->coerce(std: :move(zero), 1028 this->coerce(std: :move(zero),
1002 type ))); 1029 type )));
1003 } else if (!args[0]->fType.isNumber()) { 1030 } else if (!args[0]->fType.isNumber()) {
1004 fErrors.error(position, "invalid argument to '" + type.description() + 1031 fErrors.error(position, "invalid argument to '" + type.description() +
1005 "' constructor (expected a number or bool, b ut found '" + 1032 "' constructor (expected a number or bool, b ut found '" +
1006 args[0]->fType.description() + "')"); 1033 args[0]->fType.description() + "')");
1007 } 1034 }
1008 if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext .fInt_Type || 1035 if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext .fInt_Type ||
1009 type == *fContext.fUInt_Type)) { 1036 type == *fContext.fUInt_Type)) {
1010 return std::unique_ptr<Expression>(new IntLiteral(fContext, 1037 return std::unique_ptr<Expression>(new IntLiteral(fContext,
1011 position, 1038 position,
1012 ((IntLiteral&) *ar gs[0]).fValue, 1039 ((IntLiteral&) *ar gs[0]).fValue,
1013 &type)); 1040 &type));
1014 } 1041 }
1015 } else if (kind == Type::kArray_Kind) { 1042 } else if (kind == Type::kArray_Kind) {
1016 const Type& base = type.componentType(); 1043 const Type& base = type.componentType();
1017 for (size_t i = 0; i < args.size(); i++) { 1044 for (size_t i = 0; i < args.size(); i++) {
1018 args[i] = this->coerce(std::move(args[i]), base); 1045 args[i] = this->coerce(std::move(args[i]), base);
1046 if (!args[i]) {
1047 return nullptr;
1048 }
1019 } 1049 }
1020 } else { 1050 } else {
1021 ASSERT(kind == Type::kVector_Kind || kind == Type::kMatrix_Kind); 1051 ASSERT(kind == Type::kVector_Kind || kind == Type::kMatrix_Kind);
1022 int actual = 0; 1052 int actual = 0;
1023 for (size_t i = 0; i < args.size(); i++) { 1053 for (size_t i = 0; i < args.size(); i++) {
1024 if (args[i]->fType.kind() == Type::kVector_Kind || 1054 if (args[i]->fType.kind() == Type::kVector_Kind ||
1025 args[i]->fType.kind() == Type::kMatrix_Kind) { 1055 args[i]->fType.kind() == Type::kMatrix_Kind) {
1026 int columns = args[i]->fType.columns(); 1056 int columns = args[i]->fType.columns();
1027 int rows = args[i]->fType.rows(); 1057 int rows = args[i]->fType.rows();
1028 args[i] = this->coerce(std::move(args[i]), 1058 args[i] = this->coerce(std::move(args[i]),
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
1292 1322
1293 void IRGenerator::checkValid(const Expression& expr) { 1323 void IRGenerator::checkValid(const Expression& expr) {
1294 switch (expr.fKind) { 1324 switch (expr.fKind) {
1295 case Expression::kFunctionReference_Kind: 1325 case Expression::kFunctionReference_Kind:
1296 fErrors.error(expr.fPosition, "expected '(' to begin function call") ; 1326 fErrors.error(expr.fPosition, "expected '(' to begin function call") ;
1297 break; 1327 break;
1298 case Expression::kTypeReference_Kind: 1328 case Expression::kTypeReference_Kind:
1299 fErrors.error(expr.fPosition, "expected '(' to begin constructor inv ocation"); 1329 fErrors.error(expr.fPosition, "expected '(' to begin constructor inv ocation");
1300 break; 1330 break;
1301 default: 1331 default:
1302 ASSERT(expr.fType != *fContext.fInvalid_Type); 1332 if (expr.fType == *fContext.fInvalid_Type) {
1303 break; 1333 fErrors.error(expr.fPosition, "invalid expression");
1334 }
1304 } 1335 }
1305 } 1336 }
1306 1337
1307 void IRGenerator::markReadFrom(const Variable& var) { 1338 void IRGenerator::markReadFrom(const Variable& var) {
1308 var.fIsReadFrom = true; 1339 var.fIsReadFrom = true;
1309 } 1340 }
1310 1341
1311 static bool has_duplicates(const Swizzle& swizzle) { 1342 static bool has_duplicates(const Swizzle& swizzle) {
1312 int bits = 0; 1343 int bits = 0;
1313 for (int idx : swizzle.fComponents) { 1344 for (int idx : swizzle.fComponents) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1345 case Expression::kIndex_Kind: 1376 case Expression::kIndex_Kind:
1346 this->markWrittenTo(*((IndexExpression&) expr).fBase); 1377 this->markWrittenTo(*((IndexExpression&) expr).fBase);
1347 break; 1378 break;
1348 default: 1379 default:
1349 fErrors.error(expr.fPosition, "cannot assign to '" + expr.descriptio n() + "'"); 1380 fErrors.error(expr.fPosition, "cannot assign to '" + expr.descriptio n() + "'");
1350 break; 1381 break;
1351 } 1382 }
1352 } 1383 }
1353 1384
1354 } 1385 }
OLDNEW
« no previous file with comments | « no previous file | src/sksl/ir/SkSLTypeReference.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698