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 } | |
260 return std::unique_ptr<Statement>(new IfStatement(s.fPosition, std::move(tes
t), | 249 return std::unique_ptr<Statement>(new IfStatement(s.fPosition, std::move(tes
t), |
261 std::move(ifTrue), std::mo
ve(ifFalse))); | 250 std::move(ifTrue), std::mo
ve(ifFalse))); |
262 } | 251 } |
263 | 252 |
264 std::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) { | 253 std::unique_ptr<Statement> IRGenerator::convertFor(const ASTForStatement& f) { |
265 AutoLoopLevel level(this); | 254 AutoLoopLevel level(this); |
266 AutoSymbolTable table(this); | 255 AutoSymbolTable table(this); |
267 std::unique_ptr<Statement> initializer; | 256 std::unique_ptr<Statement> initializer; |
268 if (f.fInitializer) { | 257 if (f.fInitializer) { |
269 initializer = this->convertStatement(*f.fInitializer); | 258 initializer = this->convertStatement(*f.fInitializer); |
(...skipping 528 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
798 } | 787 } |
799 return false; | 788 return false; |
800 } | 789 } |
801 if (tryFlipped) { | 790 if (tryFlipped) { |
802 return determine_binary_type(context, op, right, left, outRightType, out
LeftType, | 791 return determine_binary_type(context, op, right, left, outRightType, out
LeftType, |
803 outResultType, false); | 792 outResultType, false); |
804 } | 793 } |
805 return false; | 794 return false; |
806 } | 795 } |
807 | 796 |
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. Note that unlike most other functi
ons here, null does | |
811 * not represent a compilation error. | |
812 */ | |
813 std::unique_ptr<Expression> IRGenerator::constantFold(const Expression& left, | |
814 Token::Kind op, | |
815 const Expression& right) { | |
816 // Note that we expressly do not worry about precision and overflow here --
we use the maximum | |
817 // precision to calculate the results and hope the result makes sense. The p
lan is to move the | |
818 // Skia caps into SkSL, so we have access to all of them including the preci
sions of the various | |
819 // types, which will let us be more intelligent about this. | |
820 if (left.fKind == Expression::kBoolLiteral_Kind && | |
821 right.fKind == Expression::kBoolLiteral_Kind) { | |
822 bool leftVal = ((BoolLiteral&) left).fValue; | |
823 bool rightVal = ((BoolLiteral&) right).fValue; | |
824 bool result; | |
825 switch (op) { | |
826 case Token::LOGICALAND: result = leftVal && rightVal; break; | |
827 case Token::LOGICALOR: result = leftVal || rightVal; break; | |
828 case Token::LOGICALXOR: result = leftVal ^ rightVal; break; | |
829 default: return nullptr; | |
830 } | |
831 return std::unique_ptr<Expression>(new BoolLiteral(fContext, left.fPosit
ion, result)); | |
832 } | |
833 #define RESULT(t, op) std::unique_ptr<Expression>(new t ## Literal(fContext,
left.fPosition, \ | |
834 leftVal o
p rightVal)) | |
835 if (left.fKind == Expression::kIntLiteral_Kind && right.fKind == Expression:
:kIntLiteral_Kind) { | |
836 int64_t leftVal = ((IntLiteral&) left).fValue; | |
837 int64_t rightVal = ((IntLiteral&) right).fValue; | |
838 switch (op) { | |
839 case Token::PLUS: return RESULT(Int, +); | |
840 case Token::MINUS: return RESULT(Int, -); | |
841 case Token::STAR: return RESULT(Int, *); | |
842 case Token::SLASH: return RESULT(Int, /); | |
843 case Token::PERCENT: return RESULT(Int, %); | |
844 case Token::BITWISEAND: return RESULT(Int, &); | |
845 case Token::BITWISEOR: return RESULT(Int, |); | |
846 case Token::BITWISEXOR: return RESULT(Int, ^); | |
847 case Token::SHL: return RESULT(Int, <<); | |
848 case Token::SHR: return RESULT(Int, >>); | |
849 case Token::EQEQ: return RESULT(Bool, ==); | |
850 case Token::NEQ: return RESULT(Bool, !=); | |
851 case Token::GT: return RESULT(Bool, >); | |
852 case Token::GTEQ: return RESULT(Bool, >=); | |
853 case Token::LT: return RESULT(Bool, <); | |
854 case Token::LTEQ: return RESULT(Bool, <=); | |
855 default: return nullptr; | |
856 } | |
857 } | |
858 if (left.fKind == Expression::kFloatLiteral_Kind && | |
859 right.fKind == Expression::kFloatLiteral_Kind) { | |
860 double leftVal = ((FloatLiteral&) left).fValue; | |
861 double rightVal = ((FloatLiteral&) right).fValue; | |
862 switch (op) { | |
863 case Token::PLUS: return RESULT(Float, +); | |
864 case Token::MINUS: return RESULT(Float, -); | |
865 case Token::STAR: return RESULT(Float, *); | |
866 case Token::SLASH: return RESULT(Float, /); | |
867 case Token::EQEQ: return RESULT(Bool, ==); | |
868 case Token::NEQ: return RESULT(Bool, !=); | |
869 case Token::GT: return RESULT(Bool, >); | |
870 case Token::GTEQ: return RESULT(Bool, >=); | |
871 case Token::LT: return RESULT(Bool, <); | |
872 case Token::LTEQ: return RESULT(Bool, <=); | |
873 default: return nullptr; | |
874 } | |
875 } | |
876 #undef RESULT | |
877 return nullptr; | |
878 } | |
879 | |
880 std::unique_ptr<Expression> IRGenerator::convertBinaryExpression( | 797 std::unique_ptr<Expression> IRGenerator::convertBinaryExpression( |
881 const ASTBinaryExpre
ssion& expression) { | 798 const ASTBinaryExpre
ssion& expression) { |
882 std::unique_ptr<Expression> left = this->convertExpression(*expression.fLeft
); | 799 std::unique_ptr<Expression> left = this->convertExpression(*expression.fLeft
); |
883 if (!left) { | 800 if (!left) { |
884 return nullptr; | 801 return nullptr; |
885 } | 802 } |
886 std::unique_ptr<Expression> right = this->convertExpression(*expression.fRig
ht); | 803 std::unique_ptr<Expression> right = this->convertExpression(*expression.fRig
ht); |
887 if (!right) { | 804 if (!right) { |
888 return nullptr; | 805 return nullptr; |
889 } | 806 } |
890 const Type* leftType; | 807 const Type* leftType; |
891 const Type* rightType; | 808 const Type* rightType; |
892 const Type* resultType; | 809 const Type* resultType; |
893 if (!determine_binary_type(fContext, expression.fOperator, left->fType, righ
t->fType, &leftType, | 810 if (!determine_binary_type(fContext, expression.fOperator, left->fType, righ
t->fType, &leftType, |
894 &rightType, &resultType, !is_assignment(expressio
n.fOperator))) { | 811 &rightType, &resultType, !is_assignment(expressio
n.fOperator))) { |
895 fErrors.error(expression.fPosition, "type mismatch: '" + | 812 fErrors.error(expression.fPosition, "type mismatch: '" + |
896 Token::OperatorName(expression.fOper
ator) + | 813 Token::OperatorName(expression.fOper
ator) + |
897 "' cannot operate on '" + left->fTyp
e.fName + | 814 "' cannot operate on '" + left->fTyp
e.fName + |
898 "', '" + right->fType.fName + "'"); | 815 "', '" + right->fType.fName + "'"); |
899 return nullptr; | 816 return nullptr; |
900 } | 817 } |
901 if (is_assignment(expression.fOperator)) { | 818 if (is_assignment(expression.fOperator)) { |
902 this->markWrittenTo(*left); | 819 this->markWrittenTo(*left); |
903 } | 820 } |
904 left = this->coerce(std::move(left), *leftType); | 821 left = this->coerce(std::move(left), *leftType); |
905 right = this->coerce(std::move(right), *rightType); | 822 right = this->coerce(std::move(right), *rightType); |
906 if (!left || !right) { | 823 if (!left || !right) { |
907 return nullptr; | 824 return nullptr; |
908 } | 825 } |
909 std::unique_ptr<Expression> result = this->constantFold(*left.get(), express
ion.fOperator, | 826 return std::unique_ptr<Expression>(new BinaryExpression(expression.fPosition
, |
910 *right.get()); | 827 std::move(left), |
911 if (!result) { | 828 expression.fOperator
, |
912 result = std::unique_ptr<Expression>(new BinaryExpression(expression.fPo
sition, | 829 std::move(right), |
913 std::move(left
), | 830 *resultType)); |
914 expression.fOp
erator, | |
915 std::move(righ
t), | |
916 *resultType)); | |
917 } | |
918 return result; | |
919 } | 831 } |
920 | 832 |
921 std::unique_ptr<Expression> IRGenerator::convertTernaryExpression( | 833 std::unique_ptr<Expression> IRGenerator::convertTernaryExpression( |
922 const ASTTernaryExpre
ssion& expression) { | 834 const ASTTernaryExpre
ssion& expression) { |
923 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*exp
ression.fTest), | 835 std::unique_ptr<Expression> test = this->coerce(this->convertExpression(*exp
ression.fTest), |
924 *fContext.fBool_Type); | 836 *fContext.fBool_Type); |
925 if (!test) { | 837 if (!test) { |
926 return nullptr; | 838 return nullptr; |
927 } | 839 } |
928 std::unique_ptr<Expression> ifTrue = this->convertExpression(*expression.fIf
True); | 840 std::unique_ptr<Expression> ifTrue = this->convertExpression(*expression.fIf
True); |
(...skipping 10 matching lines...) Expand all Loading... |
939 if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fT
ype, &trueType, | 851 if (!determine_binary_type(fContext, Token::EQEQ, ifTrue->fType, ifFalse->fT
ype, &trueType, |
940 &falseType, &resultType, true)) { | 852 &falseType, &resultType, true)) { |
941 fErrors.error(expression.fPosition, "ternary operator result mismatch: '
" + | 853 fErrors.error(expression.fPosition, "ternary operator result mismatch: '
" + |
942 ifTrue->fType.fName + "', '" + | 854 ifTrue->fType.fName + "', '" + |
943 ifFalse->fType.fName + "'"); | 855 ifFalse->fType.fName + "'"); |
944 return nullptr; | 856 return nullptr; |
945 } | 857 } |
946 ASSERT(trueType == falseType); | 858 ASSERT(trueType == falseType); |
947 ifTrue = this->coerce(std::move(ifTrue), *trueType); | 859 ifTrue = this->coerce(std::move(ifTrue), *trueType); |
948 ifFalse = this->coerce(std::move(ifFalse), *falseType); | 860 ifFalse = this->coerce(std::move(ifFalse), *falseType); |
949 if (test->fKind == Expression::kBoolLiteral_Kind) { | |
950 // static boolean test, just return one of the branches | |
951 if (((BoolLiteral&) *test).fValue) { | |
952 return ifTrue; | |
953 } else { | |
954 return ifFalse; | |
955 } | |
956 } | |
957 return std::unique_ptr<Expression>(new TernaryExpression(expression.fPositio
n, | 861 return std::unique_ptr<Expression>(new TernaryExpression(expression.fPositio
n, |
958 std::move(test), | 862 std::move(test), |
959 std::move(ifTrue), | 863 std::move(ifTrue), |
960 std::move(ifFalse))
); | 864 std::move(ifFalse))
); |
961 } | 865 } |
962 | 866 |
963 std::unique_ptr<Expression> IRGenerator::call(Position position, | 867 std::unique_ptr<Expression> IRGenerator::call(Position position, |
964 const FunctionDeclaration& functio
n, | 868 const FunctionDeclaration& functio
n, |
965 std::vector<std::unique_ptr<Expres
sion>> arguments) { | 869 std::vector<std::unique_ptr<Expres
sion>> arguments) { |
966 if (function.fParameters.size() != arguments.size()) { | 870 if (function.fParameters.size() != arguments.size()) { |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1215 } | 1119 } |
1216 this->markWrittenTo(*base); | 1120 this->markWrittenTo(*base); |
1217 break; | 1121 break; |
1218 case Token::LOGICALNOT: | 1122 case Token::LOGICALNOT: |
1219 if (base->fType != *fContext.fBool_Type) { | 1123 if (base->fType != *fContext.fBool_Type) { |
1220 fErrors.error(expression.fPosition, | 1124 fErrors.error(expression.fPosition, |
1221 "'" + Token::OperatorName(expression.fOperator) + | 1125 "'" + Token::OperatorName(expression.fOperator) + |
1222 "' cannot operate on '" + base->fType.description(
) + "'"); | 1126 "' cannot operate on '" + base->fType.description(
) + "'"); |
1223 return nullptr; | 1127 return nullptr; |
1224 } | 1128 } |
1225 if (base->fKind == Expression::kBoolLiteral_Kind) { | |
1226 return std::unique_ptr<Expression>(new BoolLiteral(fContext, bas
e->fPosition, | |
1227 !((BoolLitera
l&) *base).fValue)); | |
1228 } | |
1229 break; | 1129 break; |
1230 case Token::BITWISENOT: | 1130 case Token::BITWISENOT: |
1231 if (base->fType != *fContext.fInt_Type) { | 1131 if (base->fType != *fContext.fInt_Type) { |
1232 fErrors.error(expression.fPosition, | 1132 fErrors.error(expression.fPosition, |
1233 "'" + Token::OperatorName(expression.fOperator) + | 1133 "'" + Token::OperatorName(expression.fOperator) + |
1234 "' cannot operate on '" + base->fType.description(
) + "'"); | 1134 "' cannot operate on '" + base->fType.description(
) + "'"); |
1235 return nullptr; | 1135 return nullptr; |
1236 } | 1136 } |
1237 break; | 1137 break; |
1238 default: | 1138 default: |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1458 case Expression::kIndex_Kind: | 1358 case Expression::kIndex_Kind: |
1459 this->markWrittenTo(*((IndexExpression&) expr).fBase); | 1359 this->markWrittenTo(*((IndexExpression&) expr).fBase); |
1460 break; | 1360 break; |
1461 default: | 1361 default: |
1462 fErrors.error(expr.fPosition, "cannot assign to '" + expr.descriptio
n() + "'"); | 1362 fErrors.error(expr.fPosition, "cannot assign to '" + expr.descriptio
n() + "'"); |
1463 break; | 1363 break; |
1464 } | 1364 } |
1465 } | 1365 } |
1466 | 1366 |
1467 } | 1367 } |
OLD | NEW |