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 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
239 if (!ifTrue) { | 239 if (!ifTrue) { |
240 return nullptr; | 240 return nullptr; |
241 } | 241 } |
242 std::unique_ptr<Statement> ifFalse; | 242 std::unique_ptr<Statement> ifFalse; |
243 if (s.fIfFalse) { | 243 if (s.fIfFalse) { |
244 ifFalse = this->convertStatement(*s.fIfFalse); | 244 ifFalse = this->convertStatement(*s.fIfFalse); |
245 if (!ifFalse) { | 245 if (!ifFalse) { |
246 return nullptr; | 246 return nullptr; |
247 } | 247 } |
248 } | 248 } |
249 if (test->fKind == Expression::kBoolLiteral_Kind) { | |
250 // static boolean value, fold down to a single branch | |
251 if (((BoolLiteral&) *test).fValue) { | |
252 return ifTrue; | |
253 } else if (s.fIfFalse) { | |
254 return ifFalse; | |
255 } else { | |
256 // False & no else clause. Not an error, so don't return null! | |
257 return std::unique_ptr<Statement>(new Block(s.fPosition, { }, fSymbo lTable)); | |
258 } | |
259 } | |
249 return std::unique_ptr<Statement>(new IfStatement(s.fPosition, std::move(tes t), | 260 return std::unique_ptr<Statement>(new IfStatement(s.fPosition, std::move(tes t), |
250 std::move(ifTrue), std::mo ve(ifFalse))); | 261 std::move(ifTrue), std::mo ve(ifFalse))); |
251 } | 262 } |
252 | 263 |
253 std::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) { | 264 std::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) { |
254 AutoLoopLevel level(this); | 265 AutoLoopLevel level(this); |
255 AutoSymbolTable table(this); | 266 AutoSymbolTable table(this); |
256 std::unique_ptr<Statement> initializer; | 267 std::unique_ptr<Statement> initializer; |
257 if (f.fInitializer) { | 268 if (f.fInitializer) { |
258 initializer = this->convertStatement(*f.fInitializer); | 269 initializer = this->convertStatement(*f.fInitializer); |
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
787 } | 798 } |
788 return false; | 799 return false; |
789 } | 800 } |
790 if (tryFlipped) { | 801 if (tryFlipped) { |
791 return determine_binary_type(context, op, right, left, outRightType, out LeftType, | 802 return determine_binary_type(context, op, right, left, outRightType, out LeftType, |
792 outResultType, false); | 803 outResultType, false); |
793 } | 804 } |
794 return false; | 805 return false; |
795 } | 806 } |
796 | 807 |
808 /** | |
809 * If both operands are compile-time constants and can be folded, returns an exp ression representing | |
810 * the folded value. Otherwise, returns null. | |
811 */ | |
812 std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left, | |
813 Token::Kind op, | |
814 const Expression& right) { | |
815 if (left.fKind == Expression::kBoolLiteral_Kind && | |
816 right.fKind == Expression::kBoolLiteral_Kind) { | |
817 bool leftVal = ((BoolLiteral&) left).fValue; | |
818 bool rightVal = ((BoolLiteral&) right).fValue; | |
819 bool result; | |
820 switch (op) { | |
821 case Token::LOGICALAND: result = leftVal && rightVal; break; | |
822 case Token::LOGICALOR: result = leftVal || rightVal; break; | |
823 case Token::LOGICALXOR: result = leftVal ^ rightVal; break; | |
824 default: return nullptr; | |
825 } | |
826 return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fPosit ion, result)); | |
827 } | |
828 #define RESULT(t, op) std::unique_ptr<Expression>(new t ## Literal(fContext, left.fPosition, \ | |
829 leftVal o p rightVal)) | |
830 if (left.fKind == Expression::kIntLiteral_Kind && right.fKind == Expression: :kIntLiteral_Kind) { | |
831 int64_t leftVal = ((IntLiteral&) left).fValue; | |
dogben
2016/11/09 15:35:36
Assuming integer overflow is well-defined in SkSL,
ethannicholas
2016/11/09 16:36:21
In GLSL ES, integer precision varies. It is allowe
| |
832 int64_t rightVal = ((IntLiteral&) right).fValue; | |
833 switch (op) { | |
834 case Token::PLUS: return RESULT(Int, +); | |
835 case Token::MINUS: return RESULT(Int, -); | |
836 case Token::STAR: return RESULT(Int, *); | |
837 case Token::SLASH: return RESULT(Int, /); | |
838 case Token::PERCENT: return RESULT(Int, %); | |
839 case Token::BITWISEAND: return RESULT(Int, &); | |
840 case Token::BITWISEOR: return RESULT(Int, |); | |
841 case Token::BITWISEXOR: return RESULT(Int, ^); | |
842 case Token::SHL: return RESULT(Int, <<); | |
843 case Token::SHR: return RESULT(Int, >>); | |
844 case Token::EQEQ: return RESULT(Bool, ==); | |
845 case Token::NEQ: return RESULT(Bool, !=); | |
846 case Token::GT: return RESULT(Bool, >); | |
847 case Token::GTEQ: return RESULT(Bool, >=); | |
848 case Token::LT: return RESULT(Bool, <); | |
849 case Token::LTEQ: return RESULT(Bool, <=); | |
850 default: return nullptr; | |
851 } | |
852 } | |
853 if (left.fKind == Expression::kFloatLiteral_Kind && | |
854 right.fKind == Expression::kFloatLiteral_Kind) { | |
855 double leftVal = ((FloatLiteral&) left).fValue; | |
dogben
2016/11/09 15:35:36
Same as above, except I don't feel that strongly a
ethannicholas
2016/11/09 16:36:21
Floating point's range is allowed to be as small a
| |
856 double rightVal = ((FloatLiteral&) right).fValue; | |
857 switch (op) { | |
858 case Token::PLUS: return RESULT(Float, +); | |
859 case Token::MINUS: return RESULT(Float, -); | |
860 case Token::STAR: return RESULT(Float, *); | |
861 case Token::SLASH: return RESULT(Float, /); | |
862 case Token::EQEQ: return RESULT(Bool, ==); | |
863 case Token::NEQ: return RESULT(Bool, !=); | |
864 case Token::GT: return RESULT(Bool, >); | |
865 case Token::GTEQ: return RESULT(Bool, >=); | |
866 case Token::LT: return RESULT(Bool, <); | |
867 case Token::LTEQ: return RESULT(Bool, <=); | |
868 default: return nullptr; | |
869 } | |
870 } | |
871 #undef RESULT | |
872 return nullptr; | |
873 } | |
874 | |
797 std::unique_ptr<Expression> IRGenerator::convertBinaryExpression( | 875 std::unique_ptr<Expression> IRGenerator::convertBinaryExpression( |
798 const ASTBinaryExpre ssion& expression) { | 876 const ASTBinaryExpre ssion& expression) { |
799 std::unique_ptr<Expression> left = this->convertExpression(*expression.fLeft ); | 877 std::unique_ptr<Expression> left = this->convertExpression(*expression.fLeft ); |
800 if (!left) { | 878 if (!left) { |
801 return nullptr; | 879 return nullptr; |
802 } | 880 } |
803 std::unique_ptr<Expression> right = this->convertExpression(*expression.fRig ht); | 881 std::unique_ptr<Expression> right = this->convertExpression(*expression.fRig ht); |
804 if (!right) { | 882 if (!right) { |
805 return nullptr; | 883 return nullptr; |
806 } | 884 } |
807 const Type* leftType; | 885 const Type* leftType; |
808 const Type* rightType; | 886 const Type* rightType; |
809 const Type* resultType; | 887 const Type* resultType; |
810 if (!determine_binary_type(fContext, expression.fOperator, left->fType, righ t->fType, &leftType, | 888 if (!determine_binary_type(fContext, expression.fOperator, left->fType, righ t->fType, &leftType, |
811 &rightType, &resultType, !is_assignment(expressio n.fOperator))) { | 889 &rightType, &resultType, !is_assignment(expressio n.fOperator))) { |
812 fErrors.error(expression.fPosition, "type mismatch: '" + | 890 fErrors.error(expression.fPosition, "type mismatch: '" + |
813 Token::OperatorName(expression.fOper ator) + | 891 Token::OperatorName(expression.fOper ator) + |
814 "' cannot operate on '" + left->fTyp e.fName + | 892 "' cannot operate on '" + left->fTyp e.fName + |
815 "', '" + right->fType.fName + "'"); | 893 "', '" + right->fType.fName + "'"); |
816 return nullptr; | 894 return nullptr; |
817 } | 895 } |
818 if (is_assignment(expression.fOperator)) { | 896 if (is_assignment(expression.fOperator)) { |
819 this->markWrittenTo(*left); | 897 this->markWrittenTo(*left); |
820 } | 898 } |
821 left = this->coerce(std::move(left), *leftType); | 899 left = this->coerce(std::move(left), *leftType); |
822 right = this->coerce(std::move(right), *rightType); | 900 right = this->coerce(std::move(right), *rightType); |
823 if (!left || !right) { | 901 if (!left || !right) { |
824 return nullptr; | 902 return nullptr; |
825 } | 903 } |
826 return std::unique_ptr<Expression>(new BinaryExpression(expression.fPosition , | 904 std::unique_ptr<Expression> result = this->constantFold(*left.get(), express ion.fOperator, |
827 std::move(left), | 905 *right.get()); |
828 expression.fOperator , | 906 if (!result) { |
829 std::move(right), | 907 result = std::unique_ptr<Expression>(new BinaryExpression(expression.fPo sition, |
830 *resultType)); | 908 std::move(left ), |
909 expression.fOp erator, | |
910 std::move(righ t), | |
911 *resultType)); | |
912 } | |
913 return result; | |
831 } | 914 } |
832 | 915 |
833 std::unique_ptr<Expression> IRGenerator::convertTernaryExpression( | 916 std::unique_ptr<Expression> IRGenerator::convertTernaryExpression( |
834 const ASTTernaryExpre ssion& expression) { | 917 const ASTTernaryExpre ssion& expression) { |
835 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*exp ression.fTest), | 918 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*exp ression.fTest), |
836 *fContext.fBool_Type); | 919 *fContext.fBool_Type); |
837 if (!test) { | 920 if (!test) { |
838 return nullptr; | 921 return nullptr; |
839 } | 922 } |
840 std::unique_ptr<Expression> ifTrue = this->convertExpression(*expression.fIf True); | 923 std::unique_ptr<Expression> ifTrue = this->convertExpression(*expression.fIf True); |
(...skipping 10 matching lines...) Expand all Loading... | |
851 if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fT ype, &trueType, | 934 if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fT ype, &trueType, |
852 &falseType, &resultType, true)) { | 935 &falseType, &resultType, true)) { |
853 fErrors.error(expression.fPosition, "ternary operator result mismatch: ' " + | 936 fErrors.error(expression.fPosition, "ternary operator result mismatch: ' " + |
854 ifTrue->fType.fName + "', '" + | 937 ifTrue->fType.fName + "', '" + |
855 ifFalse->fType.fName + "'"); | 938 ifFalse->fType.fName + "'"); |
856 return nullptr; | 939 return nullptr; |
857 } | 940 } |
858 ASSERT(trueType == falseType); | 941 ASSERT(trueType == falseType); |
859 ifTrue = this->coerce(std::move(ifTrue), *trueType); | 942 ifTrue = this->coerce(std::move(ifTrue), *trueType); |
860 ifFalse = this->coerce(std::move(ifFalse), *falseType); | 943 ifFalse = this->coerce(std::move(ifFalse), *falseType); |
944 if (test->fKind == Expression::kBoolLiteral_Kind) { | |
945 // static boolean test, just return one of the branches | |
946 if (((BoolLiteral&) *test).fValue) { | |
947 return ifTrue; | |
948 } else { | |
949 return ifFalse; | |
950 } | |
951 } | |
861 return std::unique_ptr<Expression>(new TernaryExpression(expression.fPositio n, | 952 return std::unique_ptr<Expression>(new TernaryExpression(expression.fPositio n, |
862 std::move(test), | 953 std::move(test), |
863 std::move(ifTrue), | 954 std::move(ifTrue), |
864 std::move(ifFalse)) ); | 955 std::move(ifFalse)) ); |
865 } | 956 } |
866 | 957 |
867 std::unique_ptr<Expression> IRGenerator::call(Position position, | 958 std::unique_ptr<Expression> IRGenerator::call(Position position, |
868 const FunctionDeclaration& functio n, | 959 const FunctionDeclaration& functio n, |
869 std::vector<std::unique_ptr<Expres sion>> arguments) { | 960 std::vector<std::unique_ptr<Expres sion>> arguments) { |
870 if (function.fParameters.size() != arguments.size()) { | 961 if (function.fParameters.size() != arguments.size()) { |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1119 } | 1210 } |
1120 this->markWrittenTo(*base); | 1211 this->markWrittenTo(*base); |
1121 break; | 1212 break; |
1122 case Token::LOGICALNOT: | 1213 case Token::LOGICALNOT: |
1123 if (base->fType != *fContext.fBool_Type) { | 1214 if (base->fType != *fContext.fBool_Type) { |
1124 fErrors.error(expression.fPosition, | 1215 fErrors.error(expression.fPosition, |
1125 "'" + Token::OperatorName(expression.fOperator) + | 1216 "'" + Token::OperatorName(expression.fOperator) + |
1126 "' cannot operate on '" + base->fType.description( ) + "'"); | 1217 "' cannot operate on '" + base->fType.description( ) + "'"); |
1127 return nullptr; | 1218 return nullptr; |
1128 } | 1219 } |
1220 if (base->fKind == Expression::kBoolLiteral_Kind) { | |
1221 return std::unique_ptr<Expression>(new BoolLiteral(fContext, bas e->fPosition, | |
1222 !((BoolLitera l&) *base).fValue)); | |
1223 } | |
1129 break; | 1224 break; |
1130 case Token::BITWISENOT: | 1225 case Token::BITWISENOT: |
1131 if (base->fType != *fContext.fInt_Type) { | 1226 if (base->fType != *fContext.fInt_Type) { |
1132 fErrors.error(expression.fPosition, | 1227 fErrors.error(expression.fPosition, |
1133 "'" + Token::OperatorName(expression.fOperator) + | 1228 "'" + Token::OperatorName(expression.fOperator) + |
1134 "' cannot operate on '" + base->fType.description( ) + "'"); | 1229 "' cannot operate on '" + base->fType.description( ) + "'"); |
1135 return nullptr; | 1230 return nullptr; |
1136 } | 1231 } |
1137 break; | 1232 break; |
1138 default: | 1233 default: |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1358 case Expression::kIndex_Kind: | 1453 case Expression::kIndex_Kind: |
1359 this->markWrittenTo(*((IndexExpression&) expr).fBase); | 1454 this->markWrittenTo(*((IndexExpression&) expr).fBase); |
1360 break; | 1455 break; |
1361 default: | 1456 default: |
1362 fErrors.error(expr.fPosition, "cannot assign to '" + expr.descriptio n() + "'"); | 1457 fErrors.error(expr.fPosition, "cannot assign to '" + expr.descriptio n() + "'"); |
1363 break; | 1458 break; |
1364 } | 1459 } |
1365 } | 1460 } |
1366 | 1461 |
1367 } | 1462 } |
OLD | NEW |