OLD | NEW |
---|---|
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 Loading... | |
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 462 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
683 */ | 684 */ |
684 static bool determine_binary_type(const Context& context, | 685 static bool determine_binary_type(const Context& context, |
685 Token::Kind op, | 686 Token::Kind op, |
686 const Type& left, | 687 const Type& left, |
687 const Type& right, | 688 const Type& right, |
688 const Type** outLeftType, | 689 const Type** outLeftType, |
689 const Type** outRightType, | 690 const Type** outRightType, |
690 const Type** outResultType, | 691 const Type** outResultType, |
691 bool tryFlipped) { | 692 bool tryFlipped) { |
692 bool isLogical; | 693 bool isLogical; |
694 bool validMatrixOrVectorOp; | |
693 switch (op) { | 695 switch (op) { |
696 case Token::EQ: | |
697 *outLeftType = &left; | |
698 *outRightType = &left; | |
699 *outResultType = &left; | |
700 return right.canCoerceTo(left); | |
694 case Token::EQEQ: // fall through | 701 case Token::EQEQ: // fall through |
695 case Token::NEQ: // fall through | 702 case Token::NEQ: |
703 isLogical = true; | |
704 validMatrixOrVectorOp = true; | |
705 break; | |
696 case Token::LT: // fall through | 706 case Token::LT: // fall through |
697 case Token::GT: // fall through | 707 case Token::GT: // fall through |
698 case Token::LTEQ: // fall through | 708 case Token::LTEQ: // fall through |
699 case Token::GTEQ: | 709 case Token::GTEQ: |
700 isLogical = true; | 710 isLogical = true; |
711 validMatrixOrVectorOp = false; | |
701 break; | 712 break; |
702 case Token::LOGICALOR: // fall through | 713 case Token::LOGICALOR: // fall through |
703 case Token::LOGICALAND: // fall through | 714 case Token::LOGICALAND: // fall through |
704 case Token::LOGICALXOR: // fall through | 715 case Token::LOGICALXOR: // fall through |
705 case Token::LOGICALOREQ: // fall through | 716 case Token::LOGICALOREQ: // fall through |
706 case Token::LOGICALANDEQ: // fall through | 717 case Token::LOGICALANDEQ: // fall through |
707 case Token::LOGICALXOREQ: | 718 case Token::LOGICALXOREQ: |
708 *outLeftType = context.fBool_Type.get(); | 719 *outLeftType = context.fBool_Type.get(); |
709 *outRightType = context.fBool_Type.get(); | 720 *outRightType = context.fBool_Type.get(); |
710 *outResultType = context.fBool_Type.get(); | 721 *outResultType = context.fBool_Type.get(); |
(...skipping 30 matching lines...) Expand all Loading... | |
741 } else { | 752 } else { |
742 // result was a column vector, transpose it back to a ro w | 753 // result was a column vector, transpose it back to a ro w |
743 *outResultType = &(*outResultType)->toCompound(context, leftRows, | 754 *outResultType = &(*outResultType)->toCompound(context, leftRows, |
744 rightColu mns); | 755 rightColu mns); |
745 } | 756 } |
746 return leftColumns == rightRows; | 757 return leftColumns == rightRows; |
747 } else { | 758 } else { |
748 return false; | 759 return false; |
749 } | 760 } |
750 } | 761 } |
751 // fall through | 762 isLogical = false; |
763 validMatrixOrVectorOp = true; | |
764 break; | |
765 case Token::PLUS: // fall through | |
766 case Token::PLUSEQ: // fall through | |
767 case Token::MINUS: // fall through | |
768 case Token::MINUSEQ: // fall through | |
769 case Token::SLASH: // fall through | |
770 case Token::SLASHEQ: | |
771 isLogical = false; | |
772 validMatrixOrVectorOp = true; | |
773 break; | |
752 default: | 774 default: |
753 isLogical = false; | 775 isLogical = false; |
776 validMatrixOrVectorOp = false; | |
754 } | 777 } |
755 // FIXME: need to disallow illegal operations like vec3 > vec3. Also do not currently have | 778 bool isVectorOrMatrix = left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind; |
756 // full support for numbers other than float. | 779 if (left.canCoerceTo(right) && (left.kind() == Type::kScalar_Kind || |
dogben
2016/10/17 15:30:36
I don't think this is correct for the FOOEQ cases.
| |
757 if (left == right) { | 780 (isVectorOrMatrix && validMatrixOrVectorOp))) { |
758 *outLeftType = &left; | |
759 *outRightType = &left; | |
760 if (isLogical) { | |
761 *outResultType = context.fBool_Type.get(); | |
762 } else { | |
763 *outResultType = &left; | |
764 } | |
765 return true; | |
766 } | |
767 // FIXME: incorrect for shift operations | |
dogben
2016/10/17 15:30:36
I think this still applies.
| |
768 if (left.canCoerceTo(right)) { | |
769 *outLeftType = &right; | 781 *outLeftType = &right; |
770 *outRightType = &right; | 782 *outRightType = &right; |
771 if (isLogical) { | 783 if (isLogical) { |
772 *outResultType = context.fBool_Type.get(); | 784 *outResultType = context.fBool_Type.get(); |
773 } else { | 785 } else { |
774 *outResultType = &right; | 786 *outResultType = &right; |
775 } | 787 } |
776 return true; | 788 return true; |
777 } | 789 } |
778 if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) && | 790 if ((left.kind() == Type::kVector_Kind || left.kind() == Type::kMatrix_Kind) && |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
828 case Token::BITWISEOREQ: // fall through | 840 case Token::BITWISEOREQ: // fall through |
829 case Token::BITWISEXOREQ: // fall through | 841 case Token::BITWISEXOREQ: // fall through |
830 case Token::BITWISEANDEQ: // fall through | 842 case Token::BITWISEANDEQ: // fall through |
831 case Token::LOGICALOREQ: // fall through | 843 case Token::LOGICALOREQ: // fall through |
832 case Token::LOGICALXOREQ: // fall through | 844 case Token::LOGICALXOREQ: // fall through |
833 case Token::LOGICALANDEQ: | 845 case Token::LOGICALANDEQ: |
834 this->markWrittenTo(*left); | 846 this->markWrittenTo(*left); |
835 default: | 847 default: |
836 break; | 848 break; |
837 } | 849 } |
850 left = this->coerce(std::move(left), *leftType); | |
851 right = this->coerce(std::move(right), *rightType); | |
852 if (!left || !right) { | |
853 return nullptr; | |
854 } | |
838 return std::unique_ptr<Expression>(new BinaryExpression(expression.fPosition , | 855 return std::unique_ptr<Expression>(new BinaryExpression(expression.fPosition , |
839 this->coerce(std::mo ve(left), | 856 std::move(left), |
840 *leftTy pe), | |
841 expression.fOperator , | 857 expression.fOperator , |
842 this->coerce(std::mo ve(right), | 858 std::move(right), |
843 *rightT ype), | |
844 *resultType)); | 859 *resultType)); |
845 } | 860 } |
846 | 861 |
847 std::unique_ptr<Expression> IRGenerator::convertTernaryExpression( | 862 std::unique_ptr<Expression> IRGenerator::convertTernaryExpression( |
848 const ASTTernaryExpre ssion& expression) { | 863 const ASTTernaryExpre ssion& expression) { |
849 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*exp ression.fTest), | 864 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*exp ression.fTest), |
850 *fContext.fBool_Type); | 865 *fContext.fBool_Type); |
851 if (!test) { | 866 if (!test) { |
852 return nullptr; | 867 return nullptr; |
853 } | 868 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
887 " argument"; | 902 " argument"; |
888 if (function.fParameters.size() != 1) { | 903 if (function.fParameters.size() != 1) { |
889 msg += "s"; | 904 msg += "s"; |
890 } | 905 } |
891 msg += ", but found " + to_string((uint64_t) arguments.size()); | 906 msg += ", but found " + to_string((uint64_t) arguments.size()); |
892 fErrors.error(position, msg); | 907 fErrors.error(position, msg); |
893 return nullptr; | 908 return nullptr; |
894 } | 909 } |
895 for (size_t i = 0; i < arguments.size(); i++) { | 910 for (size_t i = 0; i < arguments.size(); i++) { |
896 arguments[i] = this->coerce(std::move(arguments[i]), function.fParameter s[i]->fType); | 911 arguments[i] = this->coerce(std::move(arguments[i]), function.fParameter s[i]->fType); |
912 if (!arguments[i]) { | |
913 return nullptr; | |
914 } | |
897 if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifi ers::kOut_Flag)) { | 915 if (arguments[i] && (function.fParameters[i]->fModifiers.fFlags & Modifi ers::kOut_Flag)) { |
898 this->markWrittenTo(*arguments[i]); | 916 this->markWrittenTo(*arguments[i]); |
899 } | 917 } |
900 } | 918 } |
901 return std::unique_ptr<FunctionCall>(new FunctionCall(position, function, | 919 return std::unique_ptr<FunctionCall>(new FunctionCall(position, function, |
902 std::move(arguments))) ; | 920 std::move(arguments))) ; |
903 } | 921 } |
904 | 922 |
905 /** | 923 /** |
906 * Determines the cost of coercing the arguments of a function to the required t ypes. Returns true | 924 * 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 Loading... | |
984 } | 1002 } |
985 if (args.size() == 1 && args[0]->fType == type) { | 1003 if (args.size() == 1 && args[0]->fType == type) { |
986 // argument is already the right type, just return it | 1004 // argument is already the right type, just return it |
987 return std::move(args[0]); | 1005 return std::move(args[0]); |
988 } | 1006 } |
989 if (type.isNumber()) { | 1007 if (type.isNumber()) { |
990 if (args.size() != 1) { | 1008 if (args.size() != 1) { |
991 fErrors.error(position, "invalid arguments to '" + type.description( ) + | 1009 fErrors.error(position, "invalid arguments to '" + type.description( ) + |
992 "' constructor, (expected exactly 1 argument , but found " + | 1010 "' constructor, (expected exactly 1 argument , but found " + |
993 to_string((uint64_t) args.size()) + ")"); | 1011 to_string((uint64_t) args.size()) + ")"); |
1012 return nullptr; | |
994 } | 1013 } |
995 if (args[0]->fType == *fContext.fBool_Type) { | 1014 if (args[0]->fType == *fContext.fBool_Type) { |
996 std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, position, 0)); | 1015 std::unique_ptr<IntLiteral> zero(new IntLiteral(fContext, position, 0)); |
997 std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, position, 1 )); | 1016 std::unique_ptr<IntLiteral> one(new IntLiteral(fContext, position, 1 )); |
998 return std::unique_ptr<Expression>( | 1017 return std::unique_ptr<Expression>( |
999 new TernaryExpression(position, std::mo ve(args[0]), | 1018 new TernaryExpression(position, std::mo ve(args[0]), |
1000 this->coerce(std: :move(one), type), | 1019 this->coerce(std: :move(one), type), |
1001 this->coerce(std: :move(zero), | 1020 this->coerce(std: :move(zero), |
1002 type ))); | 1021 type ))); |
1003 } else if (!args[0]->fType.isNumber()) { | 1022 } else if (!args[0]->fType.isNumber()) { |
1004 fErrors.error(position, "invalid argument to '" + type.description() + | 1023 fErrors.error(position, "invalid argument to '" + type.description() + |
1005 "' constructor (expected a number or bool, b ut found '" + | 1024 "' constructor (expected a number or bool, b ut found '" + |
1006 args[0]->fType.description() + "')"); | 1025 args[0]->fType.description() + "')"); |
1007 } | 1026 } |
1008 if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext .fInt_Type || | 1027 if (args[0]->fKind == Expression::kIntLiteral_Kind && (type == *fContext .fInt_Type || |
1009 type == *fContext.fUInt_Type)) { | 1028 type == *fContext.fUInt_Type)) { |
1010 return std::unique_ptr<Expression>(new IntLiteral(fContext, | 1029 return std::unique_ptr<Expression>(new IntLiteral(fContext, |
1011 position, | 1030 position, |
1012 ((IntLiteral&) *ar gs[0]).fValue, | 1031 ((IntLiteral&) *ar gs[0]).fValue, |
1013 &type)); | 1032 &type)); |
1014 } | 1033 } |
1015 } else if (kind == Type::kArray_Kind) { | 1034 } else if (kind == Type::kArray_Kind) { |
1016 const Type& base = type.componentType(); | 1035 const Type& base = type.componentType(); |
1017 for (size_t i = 0; i < args.size(); i++) { | 1036 for (size_t i = 0; i < args.size(); i++) { |
1018 args[i] = this->coerce(std::move(args[i]), base); | 1037 args[i] = this->coerce(std::move(args[i]), base); |
1038 if (!args[i]) { | |
1039 return nullptr; | |
1040 } | |
1019 } | 1041 } |
1020 } else { | 1042 } else { |
1021 ASSERT(kind == Type::kVector_Kind || kind == Type::kMatrix_Kind); | 1043 ASSERT(kind == Type::kVector_Kind || kind == Type::kMatrix_Kind); |
1022 int actual = 0; | 1044 int actual = 0; |
1023 for (size_t i = 0; i < args.size(); i++) { | 1045 for (size_t i = 0; i < args.size(); i++) { |
1024 if (args[i]->fType.kind() == Type::kVector_Kind || | 1046 if (args[i]->fType.kind() == Type::kVector_Kind || |
1025 args[i]->fType.kind() == Type::kMatrix_Kind) { | 1047 args[i]->fType.kind() == Type::kMatrix_Kind) { |
1026 int columns = args[i]->fType.columns(); | 1048 int columns = args[i]->fType.columns(); |
1027 int rows = args[i]->fType.rows(); | 1049 int rows = args[i]->fType.rows(); |
1028 args[i] = this->coerce(std::move(args[i]), | 1050 args[i] = this->coerce(std::move(args[i]), |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1292 | 1314 |
1293 void IRGenerator::checkValid(const Expression& expr) { | 1315 void IRGenerator::checkValid(const Expression& expr) { |
1294 switch (expr.fKind) { | 1316 switch (expr.fKind) { |
1295 case Expression::kFunctionReference_Kind: | 1317 case Expression::kFunctionReference_Kind: |
1296 fErrors.error(expr.fPosition, "expected '(' to begin function call") ; | 1318 fErrors.error(expr.fPosition, "expected '(' to begin function call") ; |
1297 break; | 1319 break; |
1298 case Expression::kTypeReference_Kind: | 1320 case Expression::kTypeReference_Kind: |
1299 fErrors.error(expr.fPosition, "expected '(' to begin constructor inv ocation"); | 1321 fErrors.error(expr.fPosition, "expected '(' to begin constructor inv ocation"); |
1300 break; | 1322 break; |
1301 default: | 1323 default: |
1302 ASSERT(expr.fType != *fContext.fInvalid_Type); | 1324 if (expr.fType == *fContext.fInvalid_Type) { |
1303 break; | 1325 fErrors.error(expr.fPosition, "invalid expression"); |
1326 } | |
1304 } | 1327 } |
1305 } | 1328 } |
1306 | 1329 |
1307 void IRGenerator::markReadFrom(const Variable& var) { | 1330 void IRGenerator::markReadFrom(const Variable& var) { |
1308 var.fIsReadFrom = true; | 1331 var.fIsReadFrom = true; |
1309 } | 1332 } |
1310 | 1333 |
1311 static bool has_duplicates(const Swizzle& swizzle) { | 1334 static bool has_duplicates(const Swizzle& swizzle) { |
1312 int bits = 0; | 1335 int bits = 0; |
1313 for (int idx : swizzle.fComponents) { | 1336 for (int idx : swizzle.fComponents) { |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1345 case Expression::kIndex_Kind: | 1368 case Expression::kIndex_Kind: |
1346 this->markWrittenTo(*((IndexExpression&) expr).fBase); | 1369 this->markWrittenTo(*((IndexExpression&) expr).fBase); |
1347 break; | 1370 break; |
1348 default: | 1371 default: |
1349 fErrors.error(expr.fPosition, "cannot assign to '" + expr.descriptio n() + "'"); | 1372 fErrors.error(expr.fPosition, "cannot assign to '" + expr.descriptio n() + "'"); |
1350 break; | 1373 break; |
1351 } | 1374 } |
1352 } | 1375 } |
1353 | 1376 |
1354 } | 1377 } |
OLD | NEW |